home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / IATHREAD.PAK / MISC.C < prev    next >
C/C++ Source or Header  |  1997-05-06  |  11KB  |  363 lines

  1. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  2. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  3. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  4. // PARTICULAR PURPOSE.
  5. //
  6. // Copyright (C) 1993-1995  Microsoft Corporation.  All Rights Reserved.
  7. //
  8. //  MODULE:   misc.c
  9. //
  10. //  PURPOSE:  Contains all helper functions "global" to the application.
  11. //
  12. //  FUNCTIONS:
  13. //    CenterWindow            - Center one window over another.
  14. //    AllocThreadData         - Allocates a thread data block.
  15. //    FreeThreadData          - Deallocates a thread data block.
  16. //    FillListBox             - Fills a listbox with strings and item data
  17. //    GetCurChildWindowThread - Returns handle of current MDI child window's
  18. //                                worker thread.
  19. //    ReducePriority    - Keeps a high priority thread from remaining
  20. //                                so forever and starving other threads.
  21. //
  22. //  COMMENTS:
  23. //
  24. //
  25.  
  26.  
  27. #include <windows.h>            // required for all Windows applications
  28. #include <windowsx.h>
  29. #include "globals.h"            // prototypes specific to this application
  30.  
  31.  
  32. //
  33. //  FUNCTION: CenterWindow(HWND, HWND)
  34. //
  35. //  PURPOSE:  Center one window over another.
  36. //
  37. //  PARAMETERS:
  38. //    hwndChild  - The handle of the window to be centered.
  39. //    hwndParent - The handle of the window to center on.
  40. //
  41. //  RETURN VALUE:
  42. //
  43. //    TRUE  - Success
  44. //    FALSE - Failure
  45. //
  46. //  COMMENTS:
  47. //
  48. //    Dialog boxes take on the screen position that they were designed
  49. //    at, which is not always appropriate. Centering the dialog over a
  50. //    particular window usually results in a better position.
  51. //
  52.  
  53. BOOL CenterWindow(HWND hwndChild, HWND hwndParent)
  54. {
  55.     RECT rcChild, rcParent;
  56.     int  cxChild, cyChild, cxParent, cyParent;
  57.     int  cxScreen, cyScreen, xNew, yNew;
  58.     HDC  hdc;
  59.  
  60.     // Get the Height and Width of the child window
  61.     GetWindowRect(hwndChild, &rcChild);
  62.     cxChild = rcChild.right - rcChild.left;
  63.     cyChild = rcChild.bottom - rcChild.top;
  64.  
  65.     // Get the Height and Width of the parent window
  66.     GetWindowRect(hwndParent, &rcParent);
  67.     cxParent = rcParent.right - rcParent.left;
  68.     cyParent = rcParent.bottom - rcParent.top;
  69.  
  70.     // Get the display limits
  71.     hdc = GetDC(hwndChild);
  72.     cxScreen = GetDeviceCaps(hdc, HORZRES);
  73.     cyScreen = GetDeviceCaps(hdc, VERTRES);
  74.     ReleaseDC(hwndChild, hdc);
  75.  
  76.     // Calculate new X position, then adjust for screen
  77.     xNew = rcParent.left + ((cxParent - cxChild) / 2);
  78.     if (xNew < 0)
  79.     {
  80.         xNew = 0;
  81.     }
  82.     else if ((xNew + cxChild) > cxScreen)
  83.     {
  84.         xNew = cxScreen - cxChild;
  85.     }
  86.  
  87.     // Calculate new Y position, then adjust for screen
  88.     yNew = rcParent.top  + ((cyParent - cyChild) / 2);
  89.     if (yNew < 0)
  90.     {
  91.         yNew = 0;
  92.     }
  93.     else if ((yNew + cyChild) > cyScreen)
  94.     {
  95.         yNew = cyScreen - cyChild;
  96.     }
  97.  
  98.     // Set it, and return
  99.     return SetWindowPos(hwndChild,
  100.                         NULL,
  101.                         xNew, yNew,
  102.                         0, 0,
  103.                         SWP_NOSIZE | SWP_NOZORDER);
  104. }
  105.  
  106.  
  107. //
  108. //  FUNCTION: AllocThreadData(void)
  109. //
  110. //  PURPOSE: To allocate a data block that will be shared between a child
  111. //           window procedure and its corresponding thread.
  112. //
  113. //  PARAMETERS: None.
  114. //
  115. //
  116. //  RETURN VALUE:
  117. //    If successful, AllocThreadData returns a pointer to the allocated
  118. //    data.
  119. //    If AllocThreadData couldn't allocate the data, it returns NULL.
  120. //
  121. //  COMMENTS:
  122. //
  123. //
  124.  
  125. PTHREAD_DATA AllocThreadData (void)
  126. {
  127.     return HeapAlloc (GetProcessHeap(),
  128.                       HEAP_ZERO_MEMORY,
  129.                       sizeof (THREAD_DATA)
  130.                      );
  131. }
  132.  
  133.  
  134. //
  135. //  FUNCTION: FreeThreadData(PTHREAD_DATA)
  136. //
  137. //  PURPOSE:  Frees the data block shared by a child window procedure
  138. //            and its corresponding thread.
  139. //
  140. //  PARAMETERS:
  141. //    pData    -  Pointer to the THREAD_DATA block to be freed.
  142. //
  143. //
  144. //  RETURN VALUE:
  145. //    TRUE  - Succeeded in freeing the data block.
  146. //    FALSE - Failed to free the data block.
  147. //
  148. //  COMMENTS:
  149. //
  150. //
  151.  
  152. BOOL FreeThreadData (PTHREAD_DATA pData)
  153. {
  154.     return HeapFree (GetProcessHeap(), 0, pData);
  155. }
  156.  
  157.  
  158. //
  159. //  FUNCTION: FillListBox(HWND, int, LPLISTBOXDATA, int)
  160. //
  161. //  PURPOSE:  To fill a listbox with strings and item data.
  162. //
  163. //  PARAMETERS:
  164. //    hdlg     -  The dialog box handle.
  165. //    int      -  Child ID of the listbox.
  166. //    lpData   -  Pointer to the list of strings and item data to put
  167. //                into the listbox.
  168. //    cItems   -  Number of items to put into the listbox--usually the
  169. //                number of items in the list pointed to by lpData.
  170. //
  171. //
  172. //  RETURN VALUE:
  173. //    TRUE  - Succeeded in filling the listbox.
  174. //    FALSE - Failed to fill listbox with all strings and item data in
  175. //            lpData.
  176. //
  177. //  COMMENTS:
  178. //
  179. //
  180.  
  181. BOOL FillListBox (HWND          hdlg,
  182.                   int           idListBox,
  183.                   LPLISTBOXDATA lpData,
  184.                   int           cItems)
  185. {
  186.     LONG lIndex, lResult;
  187.     int  i;
  188.  
  189.     for (i = 0; i < cItems; i++)
  190.     {
  191.         // Put the string into the listbox.  If an error occurs, clear the
  192.         // listbox's contents and exit.
  193.         lIndex = SendDlgItemMessage(hdlg,
  194.                                     idListBox,
  195.                                     LB_ADDSTRING,
  196.                                     0,
  197.                                     (LPARAM)lpData[i].szString);
  198.  
  199.         if (lIndex == LB_ERR || lIndex == LB_ERRSPACE)
  200.         {
  201.             SendDlgItemMessage(hdlg, idListBox, LB_RESETCONTENT, 0, 0);
  202.             return FALSE;
  203.         }
  204.  
  205.  
  206.         // Put the string's item data into the listbox.  If an error occurs,
  207.         // clear the listbox's contents and exit.
  208.         lResult = SendDlgItemMessage(hdlg,
  209.                                      idListBox,
  210.                                      LB_SETITEMDATA,
  211.                                      (WPARAM)lIndex,
  212.                                      (LPARAM)lpData[i].dwData);
  213.  
  214.         if (lResult == LB_ERR)
  215.         {
  216.             SendDlgItemMessage(hdlg, idListBox, LB_RESETCONTENT, 0, 0);
  217.             return FALSE;
  218.         }
  219.     }
  220.     return TRUE;
  221. }
  222.  
  223.  
  224. //
  225. //  FUNCTION: GetCurChildWindowThread(void)
  226. //
  227. //  PURPOSE:  To retrieve the handle of the worker thread that works on the
  228. //            currently active MDI child window.
  229. //
  230. //  PARAMETERS:
  231. //    None
  232. //
  233. //  RETURN VALUE:
  234. //    If successful, returns the thread handle that works on the active MDI
  235. //    child window.
  236. //    If unsuccessful, returns NULL.
  237. //
  238. //  COMMENTS:
  239. //
  240. //
  241.  
  242. HANDLE GetCurChildWindowThread (void)
  243.     {
  244.      PTHREAD_DATA lpThreadData;
  245.      HWND         hwndActive;
  246.      HANDLE       hThread;
  247.  
  248.  
  249.     // Get the currently active MDI child window.  If there is no active
  250.     // child window, return NULL.
  251.     // Get its thread data, and then get the thread handle out of the
  252.     // thread data.
  253.  
  254.     hwndActive = (HWND)SendMessage(ghwndMDIClient, WM_MDIGETACTIVE, 0, 0);
  255.  
  256.     if (!IsWindow(hwndActive))
  257.         return NULL;
  258.  
  259.     lpThreadData = (PTHREAD_DATA)GetWindowLong(hwndActive, GWL_USERDATA);
  260.  
  261.     // Should aways access data shared between two threads in a synchronized
  262.     // way.
  263.     EnterCriticalSection(&(lpThreadData -> csCritSec));
  264.     hThread = lpThreadData -> hThread;
  265.     LeaveCriticalSection(&(lpThreadData -> csCritSec));
  266.  
  267.     return hThread;
  268.     }
  269.  
  270.  
  271.  
  272. //
  273. //  FUNCTION: ReducePriority (PTHREAD_DATA)
  274. //
  275. //  PURPOSE:  To check a high-priority thread's watchdog timer and reduce the
  276. //            thread's priority if the time expires.  Also reduces the 
  277. //            process's priority class if needed.
  278. //
  279. //  PARAMETERS:
  280. //    pThreadData - Pointer to thread data block
  281. //
  282. //  RETURN VALUE:
  283. //    Returns TRUE if the thread's priority or process's priority class was 
  284. //    reduced; returns FALSE otherwise.
  285. //
  286. //  COMMENTS:
  287. //
  288. //    The table below lists the actions taken based on the value of the
  289. //    thread's priority watchdog timer:
  290. //
  291. //    Timer value   Meaning         Action
  292. //    -----------   -------         ------
  293. //    timer > 0     timer active    decrement timer
  294. //    timer = 0     timer expired   deactivate timer & reduce thread priority
  295. //    timer < 0     timer inactive  activate timer
  296. //
  297. //  IMPORTANT:  ReducePriority assumes that it is called inside a
  298. //              critical section.  Normally, this function should be called
  299. //              inside the thread that wants to reduce its priority after a
  300. //              given time period.
  301.  
  302. BOOL ReducePriority (PTHREAD_DATA pThreadData)
  303. {
  304.      BOOL   bReducePriorityClass;
  305.      BOOL   bReduceThreadPriority;
  306.     BOOL   bReturn               = FALSE;
  307.  
  308.      DWORD  dwPriorityClass;
  309.      int    nThreadPriority;
  310.  
  311.     HANDLE hThread               = pThreadData -> hThread;
  312.     int    nPriorityTimer        = pThreadData -> nPriorityTimer;
  313.  
  314.     dwPriorityClass = GetPriorityClass(GetCurrentProcess());
  315.     nThreadPriority = GetThreadPriority(hThread);
  316.  
  317.     // Determine if we need to reduce the thread's priority or the 
  318.     // process's priority class
  319.     bReduceThreadPriority = nThreadPriority == THREAD_PRIORITY_TIME_CRITICAL ||
  320.                             nThreadPriority == THREAD_PRIORITY_HIGHEST ||
  321.                             nThreadPriority == THREAD_PRIORITY_ABOVE_NORMAL;
  322.                             
  323.     bReducePriorityClass = dwPriorityClass == REALTIME_PRIORITY_CLASS ||
  324.                            dwPriorityClass == HIGH_PRIORITY_CLASS;
  325.            
  326.  
  327.     // If we need to reduce either the thread's priority or
  328.     // the process's priority class...
  329.     if (bReducePriorityClass || bReduceThreadPriority)
  330.     {
  331.         if (nPriorityTimer > 0)        // Timer already active
  332.         {
  333.             // Decrement timer
  334.             nPriorityTimer--;
  335.             bReturn = FALSE;
  336.         }
  337.         else if (nPriorityTimer == 0)  // Timer just expired
  338.         {
  339.             // Deactivate timer, reduce thread's priority and/or class
  340.             nPriorityTimer = -1;
  341.  
  342.             if (bReduceThreadPriority)
  343.                 SetThreadPriority(hThread, THREAD_PRIORITY_NORMAL);
  344.  
  345.             if (bReducePriorityClass)
  346.                 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
  347.  
  348.             bReturn = TRUE;
  349.         }
  350.         else                           // Timer already inactive
  351.         {
  352.             // Reactivate timer
  353.             nPriorityTimer = PRIORITY_TIMEOUT_VALUE;
  354.             bReturn = FALSE;
  355.         }
  356.  
  357.         // Save new timer value in thread's data block
  358.         pThreadData -> nPriorityTimer = nPriorityTimer;
  359.     }
  360.  
  361.     return bReturn;
  362. }
  363.